home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol06 / 05 / iconex / iconex02.c < prev    next >
Text File  |  1991-09-01  |  53KB  |  1,666 lines

  1. /*
  2.  * WINDOWS ICON EXTRACTION UTILITY - FILE READING FUNCTIONS
  3.  *
  4.  * LANGUAGE : Microsoft C 6.0
  5.  * TOOLKIT  : Windows 3.0 SDK
  6.  * MODEL    : Medium
  7.  * STATUS   : Operational
  8.  *
  9.  * Copyright (C) 1991 - All Rights Reserved
  10.  *
  11.  * Eikon Systems, Inc.
  12.  * 989 East Hillsdale Blvd, Suite 260
  13.  * Foster City, California 94404
  14.  *
  15.  * 07/08/91 - James N. Hancock - initial creation.
  16.  *
  17.  */
  18.  
  19. #include <windows.h>
  20. #include <dos.h>
  21. #include "iconex.h"
  22.  
  23. /* local defines */
  24. #define SEEK_SET                  0
  25. #define SEEK_CUR                  1
  26. #define SEEK_END                  2
  27. #define OF_ERROR                 -1
  28.  
  29. #define BITSPERBYTE               8
  30.  
  31. #define ICONHEADER_RESERVED       0
  32. #define ICONHEADER_RESOURCETYPE   1
  33.  
  34. #define ICONTYPE_UNKNOWN          0
  35. #define ICONTYPE_CGA              1
  36. #define ICONTYPE_MONO             2
  37. #define ICONTYPE_EGA              3
  38. #define ICONTYPE_VGA              4
  39. #define ICONTYPE_HIRES            5
  40.  
  41. #define MONO_PLANES               1
  42. #define MONO_BITS                 1
  43.  
  44. #define OS2EXE                    1
  45. #define WINDOWSEXE                2
  46.  
  47. #define OLDEXESIGNATURE           0x5A4D
  48. #define NEWEXESIGNATURE           0x454E
  49. #define ORDINALFLAG               0x8000
  50. #define ICONRESTYPE               0x0003
  51. #define GROUPICONRESTYPE          0x000E
  52.  
  53. /* local typedefs */
  54. typedef struct {                  /* DOS 1, 2, 3, 4 .EXE header */
  55.        USHORT   ehSignature;     /* signature bytes */
  56.        USHORT   ehcbLP;          /* bytes on last page of file */
  57.        USHORT   ehcp;            /* pages in file */
  58.        USHORT   ehcRelocation;   /* count of relocation table entries*/
  59.        USHORT   ehcParagraphHdr; /* size of header in paragraphs */
  60.        USHORT   ehMinAlloc;      /* minimum extra paragraphs needed */
  61.        USHORT   ehMaxAlloc;      /* maximum extra paragraphs needed */
  62.        USHORT   ehSS;            /* initial (relative) SS value */
  63.        USHORT   ehSP;            /* initial SP value */
  64.        USHORT   ehChecksum;      /* checksum */
  65.        USHORT   ehIP;            /* initial IP value */
  66.        USHORT   ehCS;            /* initial (relative) CS value */
  67.        USHORT   ehlpRelocation;  /* file address of relocation table */
  68.        USHORT   ehOverlayNo;     /* overlay number */
  69.        USHORT   ehReserved[16];  /* reserved words */
  70.        LONG     ehPosNewHdr;     /* file address of new exe header */
  71. } EXEHDR;                        /* eh */
  72.  
  73. typedef struct {                     /* new .EXE header */
  74.        WORD     nhSignature;         /* signature bytes */
  75.        CHAR     nhVer;               /* LINK version number */
  76.        CHAR     nhRev;               /* LINK revision number */
  77.        WORD     nhoffEntryTable;     /* offset of Entry Table */
  78.        WORD     nhcbEntryTable;      /* number of bytes in Entry Table */
  79.        LONG     nhCRC;               /* checksum of whole file */
  80.        WORD     nhFlags;             /* flag word */
  81.        WORD     nhAutoData;          /* automatic data segment number */
  82.        WORD     nhHeap;              /* initial heap allocation */
  83.        WORD     nhStack;             /* initial stack allocation */
  84.        LONG     nhCSIP;              /* initial CS:IP setting */
  85.        LONG     nhSSSP;              /* initial SS:SP setting */
  86.        WORD     nhcSeg;              /* count of file segments */
  87.        WORD     nhcMod;              /* entries in Module Reference Table*/
  88.        WORD     nhcbNonResNameTable; /* size of non-resident name table */
  89.        WORD     nhoffSegTable;       /* offset of Segment Table */
  90.        WORD     nhoffResourceTable;  /* offset of Resource Table */
  91.        WORD     nhoffResNameTable;   /* offset of Resident Name Table */
  92.        WORD     nhoffModRefTable;    /* offset of Module Reference Table */
  93.        WORD     nhoffImpNameTable;   /* offset of Imported Names Table */
  94.        LONG     nhoffNonResNameTable;/* offset of Non-resident Names Tab */
  95.        WORD     nhcMovableEntries;   /* count of movable entries */
  96.        WORD     nhcAlign;            /* segment alignment shift count */
  97.        WORD     nhCRes;              /* count of resource segments */
  98.        BYTE     nhExeType;           /* target OS (OS/2=1, Windows=2) */
  99.        BYTE     nhFlagsOther;        /* additional exe flags */
  100.        WORD     nhGangStart;         /* offset to gangload area */
  101.        WORD     nhGangLength;        /* length of gangload area */
  102.        WORD     nhSwapArea;          /* minimum code swap area size*/
  103.        WORD     nhExpVer;            /* expected Windows version number */
  104. } NEWHDR;                         /* nh */
  105.  
  106. typedef struct {                     /* resource information block */
  107.        WORD     rtType;                 /* resource type (icon = 3) */
  108.        WORD     rtCount;                /* number of resources of this type */
  109.        LONG     rtProc;                 /* reserved for runtime use */
  110. } RESTYPEINFO;                       /* rt */
  111.  
  112. typedef struct {                     /* Resource name information block */
  113.        USHORT   rnOffset;               /* file offset to resource data */
  114.        USHORT   rnLength;               /* length of resource data */
  115.        USHORT   rnFlags;                /* resource flags */
  116.        USHORT   rnID;                   /* resource name id */
  117.        USHORT   rnHandle;               /* reserved for runtime use */
  118.        USHORT   rnUsage;                /* reserved for runtime use */
  119. } RESNAMEINFO;                       /* rn */
  120. typedef RESNAMEINFO   FAR * LPRESNAMEINFO;
  121.  
  122. typedef struct {
  123.        RESTYPEINFO    rt;
  124.        RESNAMEINFO    rn[1];
  125. } RESTABLE;
  126. typedef RESTABLE FAR * LPRESTABLE;
  127.  
  128. /* The rnOffset and rnLength fields above must be shifted to compute their
  129.  * actual values.  This allows resources to be larger than 64k, but they
  130.  * do not need to be aligned on 512 byte boundaries the way segments are.
  131.  */
  132.  
  133. typedef struct {
  134.        BYTE     bWidth;
  135.        BYTE     bHeight;
  136.        BYTE     bColorCount;
  137.        BYTE     bReserved;
  138.        WORD     wPlanes;
  139.        WORD     wBitCount;
  140.        DWORD    dwBytesInRes;
  141.        WORD     wNameOrdinal;
  142. } RESDIRECTORY;
  143.  
  144. typedef struct {
  145.        BYTE     fTypeFlag;
  146.        WORD     wTypeOrdinal;
  147.        BYTE     fNameFlag;
  148.        WORD     wNameOrdinal;
  149.        WORD     wMemoryFlags;
  150.        ULONG    lSize;
  151. } RESOURCEHEADER;
  152.  
  153. /* local prototypes */
  154. static WORD  GetIconType( BITMAPINFOHEADER* );
  155. static HBITMAP GetANDBitmap( HDC, BYTE, BYTE, LPBYTE, LPBITMAPINFO, LONG );
  156. static WORD  GetBitmaps( HFILE, LPHANDLE, WORD, WORD, BYTE, BYTE, WORD,
  157.                          WORD, LONG );
  158. static BOOL     GetXORDIBits( HDC, HBITMAP, LPBYTE, LPBITMAPINFO, LONG );
  159. static HBITMAP  GetXORBitmap( HDC, BYTE, BYTE, LPBYTE, LPBITMAPINFO, LONG );
  160. static WORD     ReadExeOldHeader( HFILE, LONG, PLONG );
  161. static WORD     ReadExeNewHeader( HFILE, LONG, LONG, PLONG );
  162. static WORD     ReadExeResTable( HFILE, LONG, PHANDLE );
  163. static WORD     ReadExeIcons( HFILE, LONG, HANDLE, WORD, LPWORD, LPHANDLE );
  164. static HBITMAP  CreateCFBITMAPData( ICON );
  165. static HANDLE   CreateCFSDKPAINTData( HBITMAP );
  166.  
  167. /*
  168.  *
  169.  * IconFree( hIconData ) : WORD;
  170.  *
  171.  *        hIconData         handle to aggregate icon data to free
  172.  *
  173.  * This function performs the cleanup for the icon extraction program. It
  174.  * frees the bitmaps of any icons that were read in from disk and frees
  175.  * the dynamic memory that was allocated for storing the ICON data
  176.  * structures.
  177.  *
  178.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  179.  * error code if there are.
  180.  *
  181.  */
  182.  
  183. WORD FAR PASCAL IconFree(
  184.        HANDLE  hIconData )
  185. {
  186.        WORD    wResult;
  187.  
  188.        /* initialize */
  189.        wResult    = IDERR_SUCCESS;
  190.  
  191.        /* lock handle to icon data */
  192.        if (hIconData)
  193.        {
  194.           LPICONDATA     lpIconData;
  195.  
  196.           lpIconData = (LPICONDATA)GlobalLock( hIconData );
  197.  
  198.           if (lpIconData)
  199.           {
  200.              WORD        wArraySize;
  201.              WORD        wIndex;
  202.              LPICON      lpIconArray;
  203.  
  204.              wArraySize  = lpIconData->wArraySize;
  205.              lpIconArray = &(lpIconData->icIconArray[0]);
  206.  
  207.              /* delete bitmaps that were created for icons */
  208.              for (wIndex = 0; wIndex < wArraySize; wIndex++)
  209.              {
  210.                 if (lpIconArray[wIndex].hbmANDbits)
  211.                    DeleteObject( lpIconArray[wIndex].hbmANDbits );
  212.  
  213.                 if (lpIconArray[wIndex].hbmXORbits)
  214.                    DeleteObject( lpIconArray[wIndex].hbmXORbits );
  215.              }
  216.  
  217.              /* free globally allocated memory */
  218.              if (GlobalUnlock( hIconData ) == 0)
  219.                 GlobalFree( hIconData );
  220.              else
  221.                 wResult = IDERR_LOCKFAIL;
  222.           } else
  223.              wResult = IDERR_LOCKFAIL;
  224.        } else
  225.           wResult = IDERR_INVALIDPARAM;
  226.  
  227.        return wResult;
  228. }
  229.  
  230. /*
  231.  *
  232.  * IconCreateIcon( hWnd, hIconData, wIndex, lphIcon ) : WORD;
  233.  *
  234.  *    hWnd           window handle of the window that is creating the icon
  235.  *    hIconData      handle to aggregate data structure
  236.  *    wIndex         index to the array element that is to be used
  237.  *    lphIcon        pointer to icon handle
  238.  *
  239.  *     This function uses the information in an ICON data structure to create a
  240.  * Windows 3.0 icon through the CreateIcon function. It expects to receive a
  241.  * handle to an array of ICON data structures, plus an index to the element
  242.  * that is to be used to create the icon.
  243.  *
  244.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  245.  * error code if there are.
  246.  *
  247.  */
  248.  
  249. #define BITSPERBYTE   8
  250.  
  251. WORD FAR PASCAL IconCreateIcon(
  252.        HWND         hWnd,
  253.        HANDLE       hIconData,
  254.        WORD         wIndex,
  255.        LPHANDLE     lphIcon )
  256. {
  257.        WORD         wResult;
  258.        HANDLE       hXORbits;
  259.        HANDLE       hANDbits;
  260.        LPBYTE       lpbXORbits;
  261.        LPBYTE       lpbANDbits;
  262.        HBITMAP      hbmDestXORMask;
  263.        HBITMAP      hbmDestANDMask;
  264.        WORD         cbXORmaskSize;
  265.        WORD         cbANDmaskSize;
  266.        WORD         wIconWidth;
  267.        WORD         wIconHeight;
  268.        ICON         icIcon;
  269.  
  270.        /* initialize */
  271.        wResult     = IDERR_SUCCESS;
  272.        hXORbits    = NULL;
  273.        hANDbits    = NULL;
  274.        lpbXORbits  = NULL;
  275.        lpbANDbits  = NULL;
  276.  
  277.        /* check parameters */
  278.        if (IsWindow( hWnd ) && hIconData)
  279.        {
  280.           LPICONDATA     lpIconData;
  281.  
  282.           lpIconData = (LPICONDATA)GlobalLock( hIconData );
  283.  
  284.           if (lpIconData)
  285.           {
  286.              if (wIndex < lpIconData->wArraySize)
  287.                 /* get icon creation data */
  288.                 icIcon = lpIconData->icIconArray[wIndex];
  289.              else
  290.                 wResult = IDERR_INVALIDPARAM;
  291.  
  292.              GlobalUnlock( hIconData );
  293.           } else
  294.              wResult = IDERR_LOCKFAIL;
  295.        } else
  296.           wResult = IDERR_INVALIDPARAM;
  297.  
  298.        /* create device dependent bitmaps for an icon on this system */
  299.        if (wResult == IDERR_SUCCESS)
  300.        {
  301.           HDC     hdc;
  302.           HDC     hdcSource;
  303.           HDC     hdcDest;
  304.  
  305.           hdc = GetDC( NULL );
  306.           if (hdc)
  307.           {
  308.              /* create device-dependent bitmaps for XOR mask and AND mask */
  309.              /* then use StretchBlt() to copy bits from ICON struct's bitmaps */
  310.  
  311.              hdcSource = hdc ? CreateCompatibleDC( hdc ) : NULL;
  312.              hdcDest   = hdc ? CreateCompatibleDC( hdc ) : NULL;
  313.  
  314.              if (hdcSource && hdcDest)
  315.              {
  316.                 /* get dimensions of an icon on this system */
  317.                 wIconWidth  = GetSystemMetrics( SM_CXICON );
  318.                 wIconHeight = GetSystemMetrics( SM_CYICON );
  319.  
  320.                 /* create device-dependent bitmap for XOR mask */
  321.                 hbmDestXORMask = CreateCompatibleBitmap( hdc,
  322.                                                          wIconWidth,
  323.                                                          wIconHeight
  324.                 );
  325.  
  326.                 /* create device-dependent bitmap for monochrome AND mask */
  327.                 hbmDestANDMask = CreateBitmap(
  328.                    wIconWidth,
  329.                    wIconHeight,
  330.                    MONO_PLANES,
  331.                    MONO_BITS,
  332.                    NULL
  333.                 );
  334.  
  335.                 if (hbmDestXORMask && hbmDestANDMask)
  336.                 {
  337.                    /* copy bits for XOR mask */
  338.                    SelectObject( hdcSource, icIcon.hbmXORbits );
  339.                    SelectObject( hdcDest, hbmDestXORMask );
  340.  
  341.                    SetStretchBltMode( hdcDest, COLORONCOLOR );
  342.  
  343.                    StretchBlt( hdcDest,
  344.                                0, 0,
  345.                                wIconWidth,
  346.                                wIconHeight,
  347.                                hdcSource,
  348.                                0, 0,
  349.                                icIcon.wWidth,
  350.                                icIcon.wHeight,
  351.                                SRCCOPY
  352.                    );
  353.  
  354.                    /* copy bits for AND mask */
  355.                    SelectObject( hdcSource, icIcon.hbmANDbits );
  356.                    SelectObject( hdcDest, hbmDestANDMask );
  357.  
  358.                    SetStretchBltMode( hdcDest, BLACKONWHITE );
  359.  
  360.                    StretchBlt( hdcDest,
  361.                                0, 0,
  362.                                wIconWidth,
  363.                                wIconHeight,
  364.                                hdcSource,
  365.                                0, 0,
  366.                                icIcon.wWidth,
  367.                                icIcon.wHeight,
  368.                                SRCCOPY
  369.                    );
  370.                 } else {
  371.                    wResult = IDERR_ALLOCFAIL;
  372.                 }
  373.  
  374.                 DeleteDC( hdcSource );
  375.                 DeleteDC( hdcDest );
  376.              } else {
  377.                 wResult = IDERR_ALLOCFAIL;
  378.              }
  379.  
  380.              ReleaseDC( NULL, hdc );
  381.  
  382.           } else {
  383.              wResult = IDERR_ALLOCFAIL;
  384.           }
  385.        }
  386.  
  387.        /* allocate memory where we can store device dependent XOR bits */
  388.        if (wResult == IDERR_SUCCESS)
  389.        {
  390.           BITMAP         bm;
  391.  
  392.           if (sizeof(BITMAP) == GetObject(
  393.              hbmDestXORMask,
  394.              sizeof(BITMAP),
  395.              (LPSTR)&bm ))
  396.           {
  397.              cbXORmaskSize = (bm.bmWidth * bm.bmHeight) *
  398.                 (bm.bmPlanes * bm.bmBitsPixel) / BITSPERBYTE;
  399.  
  400.              hXORbits = GlobalAlloc( GMEM_MOVEABLE, cbXORmaskSize );
  401.  
  402.              if (hXORbits == NULL)
  403.                 wResult = IDERR_ALLOCFAIL;
  404.              else if ((lpbXORbits = (LPBYTE)GlobalLock( hXORbits )) == NULL)
  405.                 wResult = IDERR_LOCKFAIL;
  406.              else if (!GetBitmapBits( hbmDestXORMask,cbXORmaskSize,lpbXORbits))
  407.                 wResult = IDERR_WINFUNCFAIL;
  408.           } else
  409.              wResult = IDERR_WINFUNCFAIL;
  410.        }
  411.  
  412.        /* allocate memory where we can store AND bits */
  413.        if (wResult == IDERR_SUCCESS)
  414.        {
  415.           BITMAP  bm;
  416.  
  417.           if (sizeof(BITMAP) == GetObject(
  418.              hbmDestANDMask,
  419.              sizeof(BITMAP),
  420.              (LPSTR)&bm ))
  421.           {
  422.              cbANDmaskSize = (bm.bmWidth * bm.bmHeight) / BITSPERBYTE;
  423.  
  424.              hANDbits = GlobalAlloc( GMEM_MOVEABLE, cbANDmaskSize );
  425.  
  426.              if (hANDbits == NULL)
  427.                 wResult = IDERR_ALLOCFAIL;
  428.              else if ((lpbANDbits = (LPBYTE) GlobalLock( hANDbits )) == NULL)
  429.                 wResult = IDERR_LOCKFAIL;
  430.              else if (!GetBitmapBits( hbmDestANDMask,cbANDmaskSize,lpbANDbits))
  431.                 wResult = IDERR_WINFUNCFAIL;
  432.           } else
  433.              wResult = IDERR_WINFUNCFAIL;
  434.        }
  435.  
  436.        /* create the icon */
  437.        if (wResult == IDERR_SUCCESS)
  438.        {
  439.           HANDLE   hInst;
  440.           BITMAP   bm;
  441.  
  442.           if (sizeof(BITMAP) == GetObject(
  443.              hbmDestXORMask,
  444.              sizeof(BITMAP),
  445.              (LPSTR)&bm ))
  446.           {
  447.              hInst = GetWindowWord( hWnd, GWW_HINSTANCE );
  448.  
  449.              *lphIcon = CreateIcon(
  450.                 hInst,
  451.                 bm.bmWidth,
  452.                 bm.bmHeight,
  453.                 bm.bmPlanes,
  454.                 bm.bmBitsPixel,
  455.                 lpbANDbits,
  456.                 lpbXORbits
  457.              );
  458.           }
  459.  
  460.           if (*lphIcon == NULL)
  461.              wResult = IDERR_WINFUNCFAIL;
  462.        }
  463.  
  464.        /* cleanup */
  465.        if (hXORbits)
  466.        {
  467.           if (lpbXORbits)
  468.              GlobalUnlock( hXORbits );
  469.  
  470.           GlobalFree( hXORbits );
  471.        }
  472.  
  473.        if (hANDbits)
  474.        {
  475.           if (lpbANDbits)
  476.              GlobalUnlock( hANDbits );
  477.  
  478.           GlobalFree( hANDbits );
  479.        }
  480.  
  481.        if (hbmDestXORMask)
  482.           DeleteObject(hbmDestXORMask);
  483.  
  484.        if (hbmDestANDMask)
  485.           DeleteObject(hbmDestANDMask);
  486.  
  487.        return wResult;
  488. }
  489.  
  490. /*
  491.  *
  492.  * IconGetIconDescrip( hIconData, wIndex, lpszBuffer ) : WORD;
  493.  *
  494.  *        hIconData      handle to aggregate data structure
  495.  *        wIndex         index to the array element that is to be described
  496.  *        lpszBuffer     buffer for description
  497.  *
  498.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  499.  * error code if there are.
  500.  *
  501.  */
  502.  
  503. WORD FAR PASCAL IconGetIconDescrip(
  504.        HANDLE            hIconData,
  505.        WORD              wIndex,
  506.        LPSZ              lpszBuffer )
  507. {
  508.        WORD              wResult;
  509.        WORD              wIconType;
  510.        LPICONDATA        lpIconData;
  511.        LPSZ              lpszDescrip;
  512.  
  513.        /* initialize */
  514.        wResult    = IDERR_SUCCESS;
  515.        lpIconData = NULL;
  516.  
  517.        if (hIconData && lpszBuffer)
  518.        {
  519.           lpIconData = (LPICONDATA)GlobalLock( hIconData );
  520.  
  521.           if (lpIconData)
  522.           {
  523.              if (wIndex < lpIconData->wArraySize)
  524.              {
  525.                 /* determine icon type */
  526.                 wIconType = lpIconData->icIconArray[wIndex].wIconType;
  527.  
  528.                 switch (wIconType)
  529.                 {
  530.                    case ICONTYPE_CGA:
  531.                       lpszDescrip = "CGA Icon \r\n32x16,  2 Color";
  532.                       break;
  533.                    case ICONTYPE_MONO:
  534.                       lpszDescrip = "MONO Icon \r\n32x32,  2 Color";
  535.                       break;
  536.                    case ICONTYPE_EGA:
  537.                    case ICONTYPE_VGA:
  538.                       lpszDescrip = "VGA / EGA Icon \r\n32x32, 16 Color";
  539.                       break;
  540.                    case ICONTYPE_HIRES:
  541.                       lpszDescrip = "HI-RES Icon \r\n64x64, 16 Color";
  542.                       break;
  543.                    default:
  544.                       lpszDescrip = "UNKNOWN ICON";
  545.                       break;
  546.                 }
  547.  
  548.                 lstrcpy( lpszBuffer, lpszDescrip );
  549.              } else
  550.                 wResult = IDERR_INVALIDPARAM;
  551.  
  552.              GlobalUnlock( hIconData );
  553.           } else
  554.              wResult = IDERR_LOCKFAIL;
  555.        } else
  556.           wResult = IDERR_INVALIDPARAM;
  557.  
  558.        return wResult;
  559. }
  560.  
  561.  
  562.  
  563. /*
  564.  * IconCopyToClipboard( hWnd, hIconData, wIndex, wPrivateFormat ) : WORD;
  565.  *
  566.  *    hWnd           window handle of the window that is making the copy
  567.  *    hIconData      handle to aggregate data structure
  568.  *    wIndex         index to the array element that is to be copied
  569.  *    wPrivateFormat id of a private clipboard format to be used
  570.  *
  571.  * This function copies an icon to the clipboard using the SDKPAINT
  572.  * clipboard format.
  573.  *
  574.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  575.  * error code if there are.
  576.  *
  577.  */
  578.  
  579. WORD FAR PASCAL IconCopyToClipboard(
  580.        HWND              hWnd,
  581.        HANDLE            hIconData,
  582.        WORD              wIndex,
  583.        WORD              wPrivateFormat )
  584. {
  585.        WORD              wResult;
  586.        LPICONDATA        lpIconData;
  587.        ICON              icIcon;
  588.  
  589.        /* initialize */
  590.        wResult    = IDERR_SUCCESS;
  591.        lpIconData = NULL;
  592.  
  593.        if (IsWindow( hWnd ) && hIconData)
  594.        {
  595.           /* get the data for the icon to be copied */
  596.           lpIconData = (LPICONDATA)GlobalLock( hIconData );
  597.  
  598.           if (lpIconData)
  599.           {
  600.              if (wIndex < lpIconData->wArraySize)
  601.              {
  602.                 HBITMAP     hbmCFBITMAP;
  603.                 HANDLE      hmemCFSDKPAINT;
  604.  
  605.                 icIcon = lpIconData->icIconArray[wIndex];
  606.  
  607.                 if (OpenClipboard( hWnd ))
  608.                 {
  609.                    hbmCFBITMAP = CreateCFBITMAPData( icIcon );
  610.  
  611.                    if (hbmCFBITMAP)
  612.                    {
  613.                       if ( EmptyClipboard() )
  614.                       {
  615.                          SetClipboardData( CF_BITMAP, hbmCFBITMAP );
  616.  
  617.                          hmemCFSDKPAINT=CreateCFSDKPAINTData(icIcon.hbmANDbits);
  618.  
  619.                          if (wPrivateFormat && hmemCFSDKPAINT)
  620.                             SetClipboardData( wPrivateFormat, hmemCFSDKPAINT );
  621.                       }
  622.                    } else
  623.                       wResult = IDERR_ALLOCFAIL;
  624.  
  625.                    if (! CloseClipboard())
  626.                       wResult = IDERR_WINFUNCFAIL;
  627.                 } else
  628.                    wResult = IDERR_WINFUNCFAIL;
  629.              } else
  630.                 wResult = IDERR_INVALIDPARAM;
  631.  
  632.              GlobalUnlock( hIconData );
  633.  
  634.           } else
  635.              wResult = IDERR_LOCKFAIL;
  636.        } else
  637.           wResult = IDERR_INVALIDPARAM;
  638.  
  639.        return wResult;
  640. }
  641.  
  642. /*
  643.  * CreateCFBITMAPData( icIcon ) : HBITMAP;
  644.  *
  645.  *    icIcon       structure containing icon dimensions and bitmap handles
  646.  *
  647.  * This function combines an icon's AND mask and XOR mask to create a bitmap
  648.  * that can be placed on the clipboard with the CF_BITMAP format.
  649.  *
  650.  * This function returns a bitmap handle if successful or NULL
  651.  * if unsuccessful.
  652.  *
  653.  */
  654.  
  655. HBITMAP CreateCFBITMAPData(
  656.        ICON        icIcon )
  657. {
  658.        HBITMAP     hbmResult;
  659.        HDC         hdc;
  660.  
  661.        /* init */
  662.        hbmResult = NULL;
  663.  
  664.        /* get handle to device context */
  665.        hdc = GetDC( NULL );
  666.  
  667.        if (hdc)
  668.        {
  669.           HDC         hdcTarget;
  670.           HDC         hdcSource;
  671.           HBRUSH      hbrScreen;
  672.  
  673.           hdcSource = CreateCompatibleDC( hdc );
  674.  
  675.           if (hdcSource)
  676.           {
  677.              hdcTarget = CreateCompatibleDC( hdc );
  678.  
  679.              if (hdcTarget)
  680.              {
  681.                 hbrScreen = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
  682.  
  683.                 if (hbrScreen)
  684.                 {
  685.                    /* create bitmap */
  686.                    hbmResult = CreateCompatibleBitmap(
  687.                       hdc,
  688.                       icIcon.wWidth,
  689.                       icIcon.wHeight
  690.                    );
  691.  
  692.                    if (hbmResult)
  693.                    {
  694.                       /* STEP I : Fill rectangle with screen color */
  695.  
  696.                       SelectObject( hdcTarget, hbrScreen );
  697.                       SelectObject( hdcTarget, hbmResult );
  698.                       PatBlt(
  699.                          hdcTarget,
  700.                          0,
  701.                          0,
  702.                          icIcon.wWidth,
  703.                          icIcon.wHeight,
  704.                          PATCOPY
  705.                       );
  706.  
  707.                       /* STEP II : Apply the AND mask */
  708.  
  709.                       SelectObject( hdcSource, icIcon.hbmANDbits );
  710.                       BitBlt(
  711.                          hdcTarget,
  712.                          0, 0,
  713.                          icIcon.wWidth,
  714.                          icIcon.wHeight,
  715.                          hdcSource,
  716.                          0, 0,
  717.                          SRCAND
  718.                       );
  719.  
  720.                       /* STEP III : Copy the XOR mask */
  721.  
  722.                       SelectObject( hdcSource, icIcon.hbmXORbits );
  723.                       BitBlt(
  724.                          hdcTarget,
  725.                          0, 0,
  726.                          icIcon.wWidth,
  727.                          icIcon.wHeight,
  728.                          hdcSource,
  729.                          0, 0,
  730.                          SRCINVERT
  731.                       );
  732.                    }
  733.  
  734.                    DeleteObject( hbrScreen );
  735.  
  736.                 }
  737.  
  738.                 DeleteDC( hdcTarget );
  739.  
  740.              }
  741.  
  742.              DeleteDC( hdcSource );
  743.  
  744.           }
  745.  
  746.           ReleaseDC( NULL, hdc );
  747.        }
  748.  
  749.        return hbmResult;
  750. }
  751.  
  752. /*
  753.  * CreateCFSDKAPAINTData( hbmANDbits ) : HANDLE;
  754.  *
  755.  *    hbmANDbits      handle to bitmap for icon's AND mask
  756.  *
  757.  * This function allocates memory space and generates the SDK Paint private
  758.  * clipboard format. The SDKPAINT format must be registered with string
  759.  * "SDKPAINT" before use. The private SDKPAINT format data consists of:
  760.  *
  761.  *    1. a DWORD indicating the screen viewing color at the time image was
  762.  *       sent to the clipboard followed by ...
  763.  *    2. the bits of the monochrome AND image in device dependent form.
  764.  *
  765.  * This function returns the memory handle if successful or NULL if not.
  766.  *
  767.  */
  768.  
  769. HANDLE CreateCFSDKPAINTData(
  770.        HBITMAP        hbmANDbits )
  771. {
  772.        HANDLE         hmemResult;
  773.        LONG           lMemSize;
  774.        LONG           lBMPSize;
  775.        LPDWORD        lpdw;
  776.        BOOL           fSuccess;
  777.        BITMAP         bm;
  778.  
  779.        /* initialize */
  780.        hmemResult = NULL;
  781.        fSuccess   = TRUE;
  782.  
  783.        if (GetObject( hbmANDbits, sizeof(BITMAP), (LPSTR)&bm )==sizeof(BITMAP))
  784.        {
  785.           /* compute memory size to allow for alignment on 16 byte boundary */
  786.           lBMPSize = ((((bm.bmHeight * bm.bmWidth) / 8) + 15) / 16) * 16;
  787.           lMemSize = sizeof( DWORD ) + lBMPSize;
  788.  
  789.           /* allocate memory */
  790.           hmemResult = GlobalAlloc( GHND, lMemSize );
  791.           lpdw = hmemResult ? (LPDWORD) GlobalLock( hmemResult ) : NULL;
  792.  
  793.           if (lpdw)
  794.           {
  795.              /* get current screen color */
  796.              *lpdw = GetSysColor( COLOR_WINDOW );
  797.  
  798.              if (!GetBitmapBits(hbmANDbits,lBMPSize,(LPSTR)lpdw+sizeof(DWORD)))
  799.                 fSuccess = FALSE;
  800.           }
  801.           else
  802.              fSuccess = FALSE;
  803.        }
  804.        else
  805.           fSuccess = FALSE;
  806.  
  807.        /* unlock memory */
  808.        if (lpdw)
  809.           GlobalUnlock( hmemResult );
  810.  
  811.        /* clean up if unsuccessful */
  812.        if (!fSuccess && hmemResult)
  813.        {
  814.           GlobalFree( hmemResult );
  815.           hmemResult = NULL;
  816.        }
  817.  
  818.        return hmemResult;
  819. }
  820.  
  821. /*
  822.  *
  823.  * IconExtract( lpszFileName, lphIconData, lpwIconCount ) : WORD;
  824.  *
  825.  *        lpszFileName   pointer to file name string
  826.  *        lphIconData    pointer to handle to aggregate icon data
  827.  *        lpwCount       pointer to variable in which to return icon count
  828.  *
  829.  *     This function performs the following operations:
  830.  *           - opens an .exe file
  831.  *           - finds any component icons in the file
  832.  *           - dynamically allocates an array of ICON data structures
  833.  *           - fills the array of ICON data structures with all component icons
  834.  *           - closes the file
  835.  *
  836.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  837.  * error code if there are.
  838.  *
  839.  * Notes: Icons in an .exe file are organized into groups. This function
  840.  * ignores the icon groups and simply reads the individual component icons
  841.  * from the file.
  842.  *
  843.  * References: MS-DOS Encyclopedia, pp. 119-124, pp. 1487-1491.
  844.  *             Microsoft Windows Development Notes.
  845.  *             Microsoft Windows 3.0 Internal Resource Formats (11/12/90)
  846.  *
  847.  */
  848.  
  849. WORD FAR PASCAL IconExtract(
  850.        LPSZ        lpszFileName,
  851.        LPHANDLE    lphIconData,
  852.        LPWORD      lpwIconCount )
  853. {
  854.        HFILE       hFile;
  855.        HANDLE      haoff;
  856.        PWORD       paoff;
  857.        WORD        wResult;
  858.        WORD        wShiftCount;
  859.        LONG        lPos;
  860.        LONG        lPosNewHdr;
  861.        LONG        lPosResourceTable;
  862.        LONG        lFileLen;
  863.        OFSTRUCT    ofFile;
  864.  
  865.        /* initialize */
  866.        wResult       = IDERR_SUCCESS;
  867.        hFile         = OF_ERROR;
  868.        haoff         = NULL;
  869.        paoff         = NULL;
  870.        *lpwIconCount = NULL;
  871.        *lphIconData  = NULL;
  872.  
  873.        /* open file for reading */
  874.        if ((hFile = OpenFile( lpszFileName, &ofFile, OF_READ)) == OF_ERROR)
  875.           wResult = IDERR_OPENFAIL;
  876.  
  877.        /* get file length */
  878.        if (wResult == IDERR_SUCCESS)
  879.           if ((lFileLen = _llseek( hFile, 0L, SEEK_END )) == -1)
  880.              wResult = IDERR_READFAIL;
  881.  
  882.        /* read old header, verify contents, and get positon of new header */
  883.        if (wResult == IDERR_SUCCESS)
  884.           wResult = ReadExeOldHeader( hFile, lFileLen, &lPosNewHdr );
  885.  
  886.        /* read new header, verify contents, &  get position of resource table */
  887.        if (wResult == IDERR_SUCCESS)
  888.           wResult = ReadExeNewHeader(
  889.              hFile,
  890.              lFileLen,
  891.              lPosNewHdr,
  892.              &lPosResourceTable
  893.           );
  894.  
  895.        /* read shift count for file offsets of resources */
  896.        if (wResult == IDERR_SUCCESS)
  897.        {
  898.           USHORT            cb;
  899.  
  900.           /* initialize */
  901.           cb = 0;
  902.  
  903.           lPos = _llseek( hFile, lPosResourceTable, SEEK_SET );
  904.  
  905.           if (lPos == -1 || lPos > lFileLen || lPos != lPosResourceTable)
  906.              wResult = IDERR_READFAIL;
  907.  
  908.           if (wResult == IDERR_SUCCESS)
  909.              cb = _lread( hFile, (LPSTR)&wShiftCount, sizeof(wShiftCount));
  910.  
  911.           if (cb != sizeof(wShiftCount))
  912.              wResult = IDERR_READFAIL;
  913.           else if (wShiftCount > 16)
  914.              wResult = IDERR_RESTABLEBAD;
  915.        }
  916.  
  917.        /* read resource table entries and save icon offsets */
  918.        if (wResult == IDERR_SUCCESS)
  919.           wResult = ReadExeResTable( hFile, lFileLen, &haoff );
  920.  
  921.        /* read component icons from file */
  922.        if (wResult == IDERR_SUCCESS)
  923.           wResult = ReadExeIcons(
  924.              hFile,
  925.              lFileLen,
  926.              haoff,
  927.              wShiftCount,
  928.              lpwIconCount,
  929.              lphIconData
  930.           );
  931.  
  932.        /* clean up */
  933.        if (haoff)
  934.           LocalFree( haoff );
  935.  
  936.        if (hFile != OF_ERROR)
  937.           _lclose( hFile );
  938.  
  939.        return wResult;
  940. }
  941.  
  942. /*
  943.  *
  944.  * ReadExeOldHeader( hFile, lFileLen, plPosNewHdr ) : WORD;
  945.  *
  946.  *        hFile                file handle of .exe file being read
  947.  *        lFileLen             length of file
  948.  *        plPosNewHdr          pointer to file position of new header
  949.  *
  950.  *     This function reads the old header from an executable file, checks to be
  951.  * sure that it is a valid header, and saves the position of the file's
  952.  * new header.
  953.  *
  954.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  955.  * error code if there are.
  956.  *
  957.  */
  958.  
  959. WORD ReadExeOldHeader(
  960.        HFILE             hFile,
  961.        LONG              lFileLen,
  962.        PLONG             plPosNewHdr )
  963. {
  964.        LONG              lPos;
  965.        USHORT            cb;
  966.        EXEHDR            ehOldHeader;
  967.        WORD              wResult;
  968.  
  969.        /* initialize */
  970.        wResult = IDERR_SUCCESS;
  971.  
  972.        lPos = _llseek( hFile, 0L, SEEK_SET );
  973.  
  974.        if (lPos == -1 || lPos != 0L)
  975.           wResult = IDERR_READFAIL;
  976.  
  977.        if (wResult == IDERR_SUCCESS)
  978.        {
  979.           cb = _lread( hFile, (LPSTR)&ehOldHeader, sizeof(ehOldHeader) );
  980.  
  981.           if (cb != sizeof(ehOldHeader))
  982.              wResult = IDERR_READFAIL;
  983.           else if (ehOldHeader.ehSignature != OLDEXESIGNATURE)
  984.              wResult = IDERR_FILETYPEBAD;
  985.           else if (ehOldHeader.ehPosNewHdr < sizeof(EXEHDR))
  986.              wResult = IDERR_EXETYPEBAD;
  987.           else if (ehOldHeader.ehPosNewHdr > lFileLen - sizeof(NEWHDR))
  988.              wResult = IDERR_EXETYPEBAD;
  989.           else
  990.              *plPosNewHdr = ehOldHeader.ehPosNewHdr;
  991.        }
  992.  
  993.        return wResult;
  994. }
  995.  
  996. /*
  997.  *
  998.  * ReadExeNewHeader( hFile, lFileLen, lPosNewHdr, plPosResourceTable ) : WORD;
  999.  *
  1000.  *        hFile                file handle of .exe file being read
  1001.  *        lFileLen             length of file
  1002.  *        lPosNewHdr           file position of new header
  1003.  *        plPosResourceTable   pointer to file position of resource table
  1004.  *
  1005.  *     This function reads the new header from an executable file, checks to be
  1006.  * sure that it is a valid header, and saves the position of the file's
  1007.  * resource table.
  1008.  *
  1009.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  1010.  * error code if there are.
  1011.  *
  1012.  */
  1013.  
  1014. WORD ReadExeNewHeader(
  1015.        HFILE        hFile,
  1016.        LONG         lFileLen,
  1017.        LONG         lPosNewHdr,
  1018.        PLONG        plPosResourceTable )
  1019. {
  1020.        WORD         wResult;
  1021.        USHORT       cb;
  1022.        LONG         lPos;
  1023.        NEWHDR       nhNewHeader;
  1024.  
  1025.        /* initialize */
  1026.        wResult = IDERR_SUCCESS;
  1027.  
  1028.        lPos = _llseek( hFile, lPosNewHdr, SEEK_SET );
  1029.  
  1030.        if (lPos == -1 || lPos > lFileLen || lPos != lPosNewHdr)
  1031.           wResult = IDERR_READFAIL;
  1032.        else
  1033.        {
  1034.           WORD        wVersion;
  1035.  
  1036.           wVersion = (GetVersion() >> 8) | (GetVersion() << 8);
  1037.  
  1038.           cb = _lread( hFile, (LPSTR)&nhNewHeader, sizeof(nhNewHeader) );
  1039.  
  1040.           if (cb != sizeof(nhNewHeader))
  1041.              wResult = IDERR_READFAIL;
  1042.           else if (nhNewHeader.nhSignature != NEWEXESIGNATURE)
  1043.              wResult = IDERR_FILETYPEBAD;
  1044.           else if (nhNewHeader.nhExeType != WINDOWSEXE)
  1045.              wResult = IDERR_EXETYPEBAD;
  1046.           else if (nhNewHeader.nhExpVer < 0x0300)
  1047.              wResult = IDERR_WINVERSIONBAD;
  1048.           else if (nhNewHeader.nhExpVer > wVersion)
  1049.              wResult = IDERR_WINVERSIONBAD;
  1050.           else if (nhNewHeader.nhoffResourceTable == 0)
  1051.              wResult = IDERR_RESTABLEBAD;
  1052.           else
  1053.              *plPosResourceTable = lPosNewHdr + nhNewHeader.nhoffResourceTable;
  1054.        }
  1055.  
  1056.        return wResult;
  1057. }
  1058.  
  1059. /*
  1060.  *
  1061.  * ReadExeResTable( hFile, lFileLen, phaoff ) : WORD;
  1062.  *
  1063.  *        hFile          file handle of .exe file being read
  1064.  *        lFileLen       length of file
  1065.  *        phaoff         address of variable to hold memory handle
  1066.  *
  1067.  * This function reads through the entries in an .exe file's resource table,
  1068.  * identifies any icons in that table, and saves the file offsets of the data
  1069.  * for those icons. This function expects the initial file position to point
  1070.  * to the first entry in the resource table.
  1071.  *
  1072.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  1073.  * error code if there are.
  1074.  *
  1075.  */
  1076.  
  1077. WORD ReadExeResTable(
  1078.        HFILE       hFile,
  1079.        LONG        lFileLen,
  1080.        PHANDLE     phaoff )
  1081. {
  1082.        HANDLE      haoff;
  1083.        BOOL        fLoop;
  1084.        WORD        wResult;
  1085.        WORD        wLocalSize;
  1086.        LONG        lPosNextEntry;
  1087.        USHORT      iIcon;
  1088.  
  1089.        /* initialize */
  1090.        wResult       = IDERR_SUCCESS;
  1091.        fLoop         = TRUE;
  1092.        haoff         = NULL;
  1093.        iIcon         = 0;
  1094.        wLocalSize    = 1;
  1095.        lPosNextEntry = _llseek( hFile, 0L, SEEK_CUR );
  1096.  
  1097.        /* loop through entries in resource table */
  1098.        while (fLoop == TRUE)
  1099.        {
  1100.           USHORT            cb;
  1101.           USHORT            iFile;
  1102.           LONG              lPos;
  1103.           RESTYPEINFO       rt;
  1104.           PWORD             paoff;
  1105.  
  1106.           /* read RESTYPEINFO */
  1107.           cb = _lread( hFile, (LPSTR)&rt, sizeof(rt) );
  1108.           if (cb != sizeof(rt))
  1109.              wResult = IDERR_READFAIL;
  1110.           else if (rt.rtType != 0)
  1111.           {
  1112.              if (rt.rtType == (ORDINALFLAG | ICONRESTYPE))
  1113.              {
  1114.                 wLocalSize += sizeof(WORD) * rt.rtCount;
  1115.  
  1116.                 haoff = (haoff == NULL) ?
  1117.                    LocalAlloc( LMEM_FIXED, wLocalSize ) :
  1118.                    LocalReAlloc( haoff, wLocalSize, LMEM_MOVEABLE );
  1119.  
  1120.                 if (haoff == NULL)
  1121.                    wResult = IDERR_ALLOCFAIL;
  1122.                 else if ((paoff = (PWORD)LocalLock( haoff )) == NULL)
  1123.                    wResult = IDERR_LOCKFAIL;
  1124.  
  1125.                 if (wResult == IDERR_SUCCESS)
  1126.                 {
  1127.                    for (
  1128.                       iFile = 0;
  1129.                       iFile<rt.rtCount && wResult==IDERR_SUCCESS;
  1130.                       iFile++)
  1131.                    {
  1132.                       RESNAMEINFO rn;
  1133.  
  1134.                       cb = _lread( hFile, (LPSTR)&rn, sizeof(rn) );
  1135.  
  1136.                       if (cb != sizeof(rn))
  1137.                          wResult = IDERR_READFAIL;
  1138.                       else
  1139.                          paoff[iIcon++] = rn.rnOffset;
  1140.                    }
  1141.  
  1142.                    /* mark end of list */
  1143.                    paoff[iIcon] = 0;
  1144.  
  1145.                    /* unlock memory */
  1146.                    LocalUnlock( haoff );
  1147.                 }
  1148.              }
  1149.  
  1150.              if (wResult == IDERR_SUCCESS)
  1151.              {
  1152.                 lPosNextEntry += sizeof(rt) + rt.rtCount * sizeof(RESNAMEINFO);
  1153.                 lPos = _llseek( hFile, lPosNextEntry, SEEK_SET );
  1154.                 if (lPos == -1 || lPos > lFileLen || lPos != lPosNextEntry)
  1155.                    wResult = IDERR_READFAIL;
  1156.              }
  1157.           }
  1158.  
  1159.           fLoop = (rt.rtType != 0) && (wResult == IDERR_SUCCESS);
  1160.        }
  1161.  
  1162.        if (wResult == IDERR_SUCCESS && iIcon == 0)
  1163.           wResult = IDERR_NOICONS;
  1164.  
  1165.        *phaoff = haoff;
  1166.  
  1167.        /* return final result */
  1168.        return wResult;
  1169. }
  1170.  
  1171. /*
  1172.  *
  1173.  * ReadExeIcons( hFile, lFileLen, haoff, wShiftCount, lpwIconCount,
  1174.  *        lphIconData ) : WORD;
  1175.  *
  1176.  *        hFile          file handle of .exe file being read
  1177.  *        lFileLen       length of file
  1178.  *        haoff          memory handle
  1179.  *        wShiftCount    number of bits to shift file offsets
  1180.  *        lpwIconCount   pointer to word containing the number of icons read
  1181.  *        lphIconData    pointer to handle to aggregate icon data
  1182.  *
  1183.  *     This function finds the icons in an .exe file, tests their DIB headers to
  1184.  * determine if their type, and fills a data structure with their DDBs.
  1185.  *
  1186.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  1187.  * error code if there are.
  1188.  *
  1189.  */
  1190.  
  1191. WORD ReadExeIcons(
  1192.        HFILE       hFile,
  1193.        LONG        lFileLen,
  1194.        HANDLE      haoff,
  1195.        WORD        wShiftCount,
  1196.        LPWORD      lpwIconCount,
  1197.        LPHANDLE    lphIconData )
  1198. {
  1199.        USHORT      ioff;
  1200.        USHORT      iIcon;
  1201.        WORD        wResult;
  1202.        PWORD       paoff;
  1203.  
  1204.        /* initialize */
  1205.        wResult  = IDERR_SUCCESS;
  1206.        iIcon    = 0;
  1207.  
  1208.        /* lock local memory */
  1209.        paoff = haoff ? (PWORD)LocalLock( haoff ) : NULL;
  1210.        if (!paoff)
  1211.           wResult = IDERR_LOCKFAIL;
  1212.  
  1213.        /* loop through component icons */
  1214.        for (ioff = 0; (paoff[ioff] != 0) && (wResult == IDERR_SUCCESS); ioff++)
  1215.        {
  1216.           BITMAPINFOHEADER  bi;
  1217.           LONG              lPos;
  1218.           LONG              lPosDIB;
  1219.  
  1220.           lPosDIB = (LONG)paoff[ioff] << wShiftCount;
  1221.           lPos = _llseek( hFile, lPosDIB, SEEK_SET );
  1222.           if (lPos == -1 || lPos > lFileLen || lPos != lPosDIB)
  1223.              wResult = IDERR_READFAIL;
  1224.  
  1225.           /* read BITMAPINFOHEADER */
  1226.           if (wResult == IDERR_SUCCESS)
  1227.              if (_lread( hFile, (LPSTR)&bi, sizeof(bi) ) != sizeof(bi))
  1228.                 wResult = IDERR_READFAIL;
  1229.  
  1230.           /* build XOR and AND bitmaps */
  1231.           if (wResult == IDERR_SUCCESS)
  1232.           {
  1233.              WORD              wIconType;
  1234.  
  1235.              wIconType = GetIconType( &bi );
  1236.  
  1237.              if (wIconType != ICONTYPE_UNKNOWN)
  1238.              {
  1239.                 WORD  wColorTableSize;
  1240.                 WORD  wDIBHeaderSize;
  1241.                 WORD  wImageSize;
  1242.                 WORD  wDIBSize;
  1243.  
  1244.                 /* calculate combined size of XOR & AND masks */
  1245.                 wImageSize = (WORD)(bi.biWidth * (bi.biHeight / 2)) *
  1246.                              (WORD)(bi.biBitCount + 1) / BITSPERBYTE;
  1247.  
  1248.                 /* calculate size of entire DIB */
  1249.                 wColorTableSize = sizeof(RGBQUAD) * (0x0001 << bi.biBitCount);
  1250.                 wDIBHeaderSize = (WORD)bi.biSize + wColorTableSize;
  1251.                 wDIBSize = wDIBHeaderSize + wImageSize;
  1252.  
  1253.                 wResult = GetBitmaps(
  1254.                    hFile,
  1255.                    lphIconData,
  1256.                    iIcon,
  1257.                    wIconType,
  1258.                    (BYTE)bi.biWidth,
  1259.                    (BYTE)(bi.biHeight / 2),
  1260.                    wDIBHeaderSize,
  1261.                    wDIBSize,
  1262.                    lPosDIB
  1263.                 );
  1264.  
  1265.                 iIcon++;
  1266.              }
  1267.           }
  1268.        }
  1269.  
  1270.        /* set error code if no icons found, or free memory if error occurred */
  1271.        if (wResult == IDERR_SUCCESS)
  1272.        {
  1273.           if (iIcon == 0)
  1274.              wResult = IDERR_NOICONS;
  1275.        }
  1276.        else
  1277.        {
  1278.           if (iIcon > 0)
  1279.           {
  1280.              IconFree( *lphIconData );
  1281.              iIcon = 0;
  1282.           }
  1283.        }
  1284.  
  1285.        *lpwIconCount = iIcon;
  1286.  
  1287.        /* unlock memory */
  1288.        if (paoff)
  1289.           LocalUnlock( haoff );
  1290.  
  1291.        /* return final result */
  1292.        return wResult;
  1293. }
  1294.  
  1295. /*
  1296.  * GetBitmaps(  hFile, lphIconData, iIcon, wIconType, bWidth, bHeight,
  1297.  *              wDIBHeaderSize, wDIBSize, lPosDIB ) : WORD;
  1298.  *
  1299.  *    hFile          file handle
  1300.  *    lphIconData    pointer to handle to aggregate icon data
  1301.  *    iIcon          index to ICON array
  1302.  *    wIconType      icon type identifer
  1303.  *    bWidth         icon width
  1304.  *    bHeight        icon height
  1305.  *    wDIBHeaderSize size of DIB header including color table
  1306.  *    wDIBSize       device independent bitmap size
  1307.  *    lPosDIB        file offset of the DIB
  1308.  *
  1309.  * This function computes XOR and AND mask bitmaps and fills the ICON data
  1310.  * structure.
  1311.  *
  1312.  * This function returns IDERR_SUCCESS if there are no errors, or a non-zero
  1313.  * error code if there are.
  1314.  *
  1315.  */
  1316.  
  1317. WORD GetBitmaps(
  1318.        HFILE       hFile,
  1319.        LPHANDLE    lphIconData,
  1320.        WORD        iIcon,
  1321.        WORD        wIconType,
  1322.        BYTE        bWidth,
  1323.        BYTE        bHeight,
  1324.        WORD        wDIBHeaderSize,
  1325.        WORD        wDIBSize,
  1326.        LONG        lPosDIB )
  1327. {
  1328.        LPSTR       lpDIB;
  1329.        HANDLE      hMemDIB;
  1330.        WORD        wResult;
  1331.  
  1332.        /* initialization */
  1333.        wResult = IDERR_SUCCESS;
  1334.        hMemDIB = NULL;
  1335.        lpDIB   = NULL;
  1336.  
  1337.        /* allocate memory for the DIB */
  1338.  
  1339.        if ((hMemDIB = GlobalAlloc( GMEM_MOVEABLE, wDIBSize )) == NULL)
  1340.           wResult = IDERR_ALLOCFAIL;
  1341.        else if ((lpDIB = GlobalLock( hMemDIB )) == NULL)
  1342.           wResult = IDERR_LOCKFAIL;
  1343.  
  1344.        /* read in device independent bitmaps for both the AND and XOR masks */
  1345.        /* the file position is set, so that the BITMAPINFOHEADER is reread */
  1346.  
  1347.        if (wResult == IDERR_SUCCESS)
  1348.           if ((_llseek( hFile, lPosDIB, SEEK_SET ) != lPosDIB)
  1349.              || (WORD)(_lread( hFile, lpDIB, wDIBSize ) != wDIBSize))
  1350.              wResult = IDERR_READFAIL;
  1351.  
  1352.        /* create device-dependent bitmaps and copy DIB bits to them from the */
  1353.        /* bits that were read in from disk */
  1354.  
  1355.        if (wResult == IDERR_SUCCESS)
  1356.        {
  1357.           LPBITMAPINFO   lpbmiXORinfo;
  1358.           HDC            hdc;
  1359.           USHORT         cbXORmaskSize;
  1360.           USHORT         cbANDmaskSize;
  1361.           LPBYTE         lpbDIBANDbits;
  1362.           LPBYTE         lpbDIBXORbits;
  1363.           HBITMAP        hbmXORbits;
  1364.           HBITMAP        hbmANDbits;
  1365.  
  1366.           /* point to BITMAPINFO structure at beginning of DIB */
  1367.           lpbmiXORinfo = (LPBITMAPINFO)lpDIB;
  1368.  
  1369.           /* calculate mask sizes */
  1370.           cbXORmaskSize = ((bWidth * bHeight) *
  1371.              lpbmiXORinfo->bmiHeader.biBitCount) / BITSPERBYTE;
  1372.           cbANDmaskSize = (bWidth * bHeight) / BITSPERBYTE;
  1373.  
  1374.           /* calculate offsets to bitmap bits */
  1375.           lpbDIBXORbits = lpDIB + wDIBHeaderSize;
  1376.           lpbDIBANDbits = lpbDIBXORbits + cbXORmaskSize;
  1377.  
  1378.           hdc = GetDC( NULL );
  1379.  
  1380.           if (hdc)
  1381.           {
  1382.              lpbmiXORinfo->bmiHeader.biHeight = bHeight;
  1383.              hbmXORbits = GetXORBitmap(
  1384.                 hdc,
  1385.                 bWidth,
  1386.                 bHeight,
  1387.                 lpbDIBXORbits,
  1388.                 lpbmiXORinfo,
  1389.                 cbXORmaskSize
  1390.              );
  1391.  
  1392.              if (hbmXORbits)
  1393.              {
  1394.                 hbmANDbits = GetANDBitmap(
  1395.                    hdc,
  1396.                    bWidth,
  1397.                    bHeight,
  1398.                    lpbDIBANDbits,
  1399.                    lpbmiXORinfo,
  1400.                    cbANDmaskSize
  1401.                 );
  1402.  
  1403.                 /* allocate memory and fill out the ICON data structure */
  1404.                 if (hbmANDbits)
  1405.                 {
  1406.                    BITMAP   bm;
  1407.                    USHORT   cb;
  1408.  
  1409.                    cb = GetObject( hbmXORbits, sizeof(BITMAP), (LPSTR)&bm );
  1410.  
  1411.                    if (cb == sizeof(BITMAP))
  1412.                    {
  1413.                       HANDLE   hIconData;
  1414.  
  1415.                       /* initialize */
  1416.                       hIconData = *lphIconData;
  1417.  
  1418.                       if (hIconData)
  1419.                          hIconData = GlobalReAlloc(
  1420.                             hIconData,
  1421.                             sizeof(ICONDATA) + (iIcon * sizeof(ICON)),
  1422.                             GMEM_MOVEABLE
  1423.                          );
  1424.                       else
  1425.                          hIconData = GlobalAlloc(
  1426.                             GMEM_MOVEABLE,
  1427.                             sizeof(ICONDATA)
  1428.                          );
  1429.  
  1430.                       if (hIconData)
  1431.                       {
  1432.                          LPICONDATA  lpIconData;
  1433.  
  1434.                          *lphIconData = hIconData;
  1435.  
  1436.                          lpIconData = (LPICONDATA)GlobalLock( hIconData );
  1437.  
  1438.                          if (lpIconData)
  1439.                          {
  1440.                             ICON  icTemp;
  1441.  
  1442.                             icTemp.wIconType  = wIconType;
  1443.                             icTemp.wWidth     = bm.bmWidth;
  1444.                             icTemp.wHeight    = bm.bmHeight;
  1445.                             icTemp.bPlanes    = bm.bmPlanes;
  1446.                             icTemp.bBitsPixel = bm.bmBitsPixel;
  1447.                             icTemp.hbmANDbits = hbmANDbits;
  1448.                             icTemp.hbmXORbits = hbmXORbits;
  1449.                             icTemp.lFilePos   = lPosDIB;
  1450.  
  1451.                             lpIconData->wArraySize = iIcon + 1;
  1452.                             lpIconData->icIconArray[iIcon] = icTemp;
  1453.                             GlobalUnlock( hIconData );
  1454.                          } else
  1455.                             wResult = IDERR_LOCKFAIL;
  1456.                       } else
  1457.                          wResult = IDERR_ALLOCFAIL;
  1458.                    }
  1459.                 }
  1460.              }
  1461.              ReleaseDC( NULL, hdc );
  1462.           } else {
  1463.              wResult = IDERR_ALLOCFAIL;
  1464.           }
  1465.  
  1466.           if (wResult != IDERR_SUCCESS)
  1467.           {
  1468.              if (hbmXORbits)
  1469.                 DeleteObject( hbmXORbits );
  1470.              if (hbmANDbits)
  1471.                 DeleteObject( hbmANDbits );
  1472.           }
  1473.        } /* end if (wResult == IDERR_SUCCESS) */
  1474.  
  1475.        /* clean up */
  1476.        if (hMemDIB)
  1477.        {
  1478.           if (lpDIB)
  1479.              GlobalUnlock( hMemDIB );
  1480.  
  1481.           GlobalFree( hMemDIB );
  1482.        }
  1483.  
  1484.        /* return value */
  1485.        return wResult;
  1486. }
  1487.  
  1488. /*
  1489.  * GetIconType( lpbi ) : WORD;
  1490.  *
  1491.  *    lpbi               points to BITMAPINFOHEADER component of DIB header
  1492.  *
  1493.  * This function checks the height, width, and color count of the specified
  1494.  * DIB to determine if they match known icon types.
  1495.  *
  1496.  * This function returns a code identifying the icon type. It returns the value
  1497.  * ICONTYPE_UNKNOWN if the icon type could not be determined.
  1498.  *
  1499.  */
  1500.  
  1501.  WORD GetIconType(
  1502.        BITMAPINFOHEADER* lpbi )
  1503. {
  1504.        typedef const struct {
  1505.           WORD     wIconType;
  1506.           WORD     wWidth;
  1507.           WORD     wHeight;
  1508.           WORD     wBitCount;
  1509.        } ICONPARAMS;
  1510.  
  1511.        WORD              wResult;
  1512.        WORD              wIndex;
  1513.        BITMAPINFOHEADER  biTemp;
  1514.        ICONPARAMS        ip[] = {
  1515.           {ICONTYPE_CGA,    32, 16, 1},
  1516.           {ICONTYPE_MONO,   32, 32, 1},
  1517.           {ICONTYPE_EGA,    32, 32, 4},
  1518.           {ICONTYPE_VGA,    32, 32, 4},
  1519.           {ICONTYPE_HIRES,  64, 64, 4},
  1520.           {ICONTYPE_UNKNOWN, 0,  0, 0} };
  1521.  
  1522.        /* initialize */
  1523.        wResult = ICONTYPE_UNKNOWN;
  1524.        biTemp  = *lpbi;
  1525.  
  1526.        /* check to see if current icon matches a known type */
  1527.        for (wIndex = 0; wIndex < (sizeof(ip) / sizeof(ICONPARAMS)); wIndex++)
  1528.           if ((biTemp.biWidth    == ip[wIndex].wWidth) &&
  1529.               (biTemp.biHeight   == ip[wIndex].wHeight * 2) &&
  1530.               (biTemp.biBitCount == ip[wIndex].wBitCount))
  1531.           {
  1532.              wResult = ip[wIndex].wIconType;
  1533.              break;
  1534.           }
  1535.  
  1536.        /* return value */
  1537.        return wResult;
  1538. }
  1539.  
  1540. /*
  1541.  * GetXORBitmap( hdc, bWidth, bHeight, lpbBits, lpbmpInfo, lSize )
  1542.  *        : HBITMAP;
  1543.  *
  1544.  *    hdc            device context handle
  1545.  *    bWidth         icon width
  1546.  *    bHeight        icon height
  1547.  *    lpbBits        bitmap bits
  1548.  *    lpbmpInfo      pointer to BITMAPINFO struct
  1549.  *    lSize          bitmap size
  1550.  *
  1551.  * This function creates an XOR mask bitmap.
  1552.  *
  1553.  * This function returns the handle to the bitmap if it is successful, or NULL
  1554.  * if it fails.
  1555.  *
  1556.  */
  1557.  
  1558. HBITMAP GetXORBitmap(
  1559.        HDC            hdc,
  1560.        BYTE           bWidth,
  1561.        BYTE           bHeight,
  1562.        LPBYTE         lpbBits,
  1563.        LPBITMAPINFO   lpbmpInfo,
  1564.        LONG           lSize )
  1565. {
  1566.        HBITMAP     hbmp;
  1567.  
  1568.        /* create device-dependent bitmap for XOR mask */
  1569.        hbmp = CreateCompatibleBitmap( hdc, bWidth, bHeight );
  1570.  
  1571.        if (hbmp)
  1572.        {
  1573.           USHORT      usScanLineCount;
  1574.  
  1575.           /* modify BITMAPINFOHEADER structure for color bitmap */
  1576.           lpbmpInfo->bmiHeader.biSizeImage = lSize;
  1577.  
  1578.           /* convert XOR mask from DIB to device-dependent bitmap */
  1579.           usScanLineCount = SetDIBits(
  1580.              hdc,
  1581.              hbmp,
  1582.              0,
  1583.              bHeight,
  1584.              lpbBits,
  1585.              lpbmpInfo,
  1586.              DIB_RGB_COLORS
  1587.           );
  1588.  
  1589.           if (usScanLineCount == 0)
  1590.           {
  1591.              DeleteObject( hbmp );
  1592.              hbmp = NULL;
  1593.           }
  1594.        }
  1595.  
  1596.        /* return value */
  1597.        return hbmp;
  1598. }
  1599.  
  1600.  
  1601.  
  1602. /*
  1603.  * GetANDBitmap( hdc, bWidth, bHeight, lpbBits, lpbmpInfo, lSize ) : HBITMAP;
  1604.  *
  1605.  *    hdc            device context handle
  1606.  *    bWidth         icon width
  1607.  *    bHeight        icon height
  1608.  *    lpbBits        bitmap bits
  1609.  *    lpbmpInfo      pointer to BITMAPINFO struct
  1610.  *    lSize          bitmap size
  1611.  *
  1612.  * This function creates an AND mask bitmap.
  1613.  *
  1614.  * This function returns the handle to the bitmap if it is successful, or NULL
  1615.  * if it fails.
  1616.  *
  1617.  */
  1618.  
  1619. HBITMAP GetANDBitmap(
  1620.        HDC            hdc,
  1621.        BYTE           bWidth,
  1622.        BYTE           bHeight,
  1623.        LPBYTE         lpbBits,
  1624.        LPBITMAPINFO   lpbmpInfo,
  1625.        LONG           lSize )
  1626. {
  1627.        HBITMAP        hbmp;
  1628.  
  1629.        /* create device-dependent bitmap for AND mask */
  1630.        hbmp = CreateBitmap( bWidth, bHeight, MONO_PLANES, MONO_BITS, NULL );
  1631.        if (hbmp)
  1632.        {
  1633.           const RGBQUAD     rBlack = { 0x00, 0x00, 0x00, 0x00 };
  1634.           const RGBQUAD     rWhite = { 0xFF, 0xFF, 0xFF, 0x00 };
  1635.           USHORT            usScanLineCount;
  1636.  
  1637.           /* modify BITMAPINFOHEADER structure for monochrome bitmap */
  1638.           lpbmpInfo->bmiHeader.biHeight = bHeight;
  1639.           lpbmpInfo->bmiHeader.biSizeImage = lSize;
  1640.           lpbmpInfo->bmiHeader.biBitCount = 1;
  1641.           lpbmpInfo->bmiColors[0] = rBlack;
  1642.           lpbmpInfo->bmiColors[1] = rWhite;
  1643.  
  1644.           /* convert AND mask from DIB to device-dependent bitmap */
  1645.           usScanLineCount = SetDIBits(
  1646.              hdc,
  1647.              hbmp,
  1648.              0,
  1649.              bHeight,
  1650.              lpbBits,
  1651.              lpbmpInfo,
  1652.              DIB_RGB_COLORS
  1653.           );
  1654.  
  1655.           if (usScanLineCount == 0)
  1656.           {
  1657.              DeleteObject( hbmp );
  1658.              hbmp = NULL;
  1659.           }
  1660.        }
  1661.  
  1662.        /* return value */
  1663.        return hbmp;
  1664. }
  1665.  
  1666.